home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PROGEDIT / H402.ZIP / ELV17SRC.ZIP / REGSUB.C < prev    next >
C/C++ Source or Header  |  1992-12-30  |  5KB  |  246 lines

  1. /* regsub.c */
  2.  
  3. /* This file contains the regsub() function, which performs substitutions
  4.  * after a regexp match has been found.
  5.  */
  6.  
  7. #include "config.h"
  8. #include "ctype.h"
  9. #include "vi.h"
  10. #include "regexp.h"
  11.  
  12.  
  13. /* perform substitutions after a regexp match */
  14. void regsub(re, src, dst)
  15.     regexp        *re;    /* the regexp with pointers into matched text */
  16.     REG char    *src;    /* the replacement string */
  17.     REG char    *dst;    /* where to put the result of the subst */
  18. {
  19.     REG char    *cpy;    /* pointer to start of text to copy */
  20.     REG char    *end;    /* pointer to end of text to copy */
  21.     REG char    c;
  22.     char        *start;
  23. #ifndef CRUNCH
  24.     int        mod = 0;/* used to track \U, \L, \u, \l, and \E */
  25.     int        len;    /* used to calculate length of subst string */
  26.     static char    *prev;    /* a copy of the text from the previous subst */
  27.  
  28.     /* replace \~ (or maybe ~) by previous substitution text */
  29.  
  30.     /* step 1: calculate the length of the new substitution text */
  31.     for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++)
  32.     {
  33. # ifdef NO_MAGIC
  34.         if (c == '\\' && *cpy == '~')
  35. # else
  36.         if (c == (*o_magic ? '\0' : '\\') && *cpy == '~')
  37. # endif
  38.         {
  39.             if (!prev)
  40.             {
  41.                 regerror("No prev text to substitute for ~");
  42.                 return;
  43.             }
  44.             len += strlen(prev) - 1;
  45. # ifndef NO_MAGIC
  46.             if (!*o_magic)
  47. # endif
  48.                 len -= 1; /* because we lose the \ too */
  49.         }
  50.  
  51.         /* watch backslash quoting */
  52.         if (c != '\\' && *cpy == '\\')
  53.             c = '\\';
  54.         else
  55.             c = '\0';
  56.     }
  57.  
  58.     /* allocate memory for the ~ed version of src */
  59.     checkmem();
  60.     start = cpy = (char *)malloc((unsigned)(len + 1));
  61.     if (!cpy)
  62.     {
  63.         regerror("Not enough memory for ~ expansion");
  64.         return;
  65.     }
  66.  
  67.     /* copy src into start, replacing the ~s by the previous text */
  68.     while (*src)
  69.     {
  70. # ifndef NO_MAGIC
  71.         if (*o_magic && *src == '~')
  72.         {
  73.             strcpy(cpy, prev);
  74.             cpy += strlen(prev);
  75.             src++;
  76.         }
  77.         else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
  78. # else /* NO_MAGIC */
  79.         if (*src == '\\' && *(src + 1) == '~')
  80. # endif /* NO_MAGIC */
  81.         {
  82.             strcpy(cpy, prev);
  83.             cpy += strlen(prev);
  84.             src += 2;
  85.         }
  86.         else
  87.         {
  88.             *cpy++ = *src++;
  89.         }
  90.     }
  91.     *cpy = '\0';
  92. #ifdef DEBUG
  93.     if ((int)(cpy - start) != len)
  94.     {
  95.         msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
  96.     }
  97. #endif
  98.     checkmem();
  99.  
  100.     /* remember this as the "previous" for next time */
  101.     if (prev)
  102.         _free_(prev);
  103.     prev = src = start;
  104.  
  105. #endif /* undef CRUNCH */
  106.  
  107.     start = src;
  108.     while ((c = *src++) != '\0')
  109.     {
  110. #ifndef NO_MAGIC
  111.         /* recognize any meta characters */
  112.         if (c == '&' && *o_magic)
  113.         {
  114.             cpy = re->startp[0];
  115.             end = re->endp[0];
  116.         }
  117.         else
  118. #endif /* not NO_MAGIC */
  119.         if (c == '\\')
  120.         {
  121.             c = *src++;
  122.             switch (c)
  123.             {
  124. #ifndef NO_MAGIC
  125.               case '0':
  126.               case '1':
  127.               case '2':
  128.               case '3':
  129.               case '4':
  130.               case '5':
  131.               case '6':
  132.               case '7':
  133.               case '8':
  134.               case '9':
  135.                 /* \0 thru \9 mean "copy subexpression" */
  136.                 c -= '0';
  137.                 cpy = re->startp[c];
  138.                 end = re->endp[c];
  139.                 break;
  140. # ifndef CRUNCH
  141.               case 'U':
  142.               case 'u':
  143.               case 'L':
  144.               case 'l':
  145.                 /* \U and \L mean "convert to upper/lowercase" */
  146.                 mod = c;
  147.                 continue;
  148.  
  149.               case 'E':
  150.               case 'e':
  151.                 /* \E ends the \U or \L */
  152.                 mod = 0;
  153.                 continue;
  154. # endif /* not CRUNCH */
  155.               case '&':
  156.                 /* "\&" means "original text" */
  157.                 if (*o_magic)
  158.                 {
  159.                     *dst++ = c;
  160.                     continue;
  161.                 }
  162.                 cpy = re->startp[0];
  163.                 end = re->endp[0];
  164.                 break;
  165.  
  166. #else /* NO_MAGIC */
  167.               case '&':
  168.                 /* "\&" means "original text" */
  169.                 cpy = re->startp[0];
  170.                 end = re->endp[0];
  171.                 break;
  172. #endif /* NO_MAGIC */
  173.               default:
  174.                 /* ordinary char preceded by backslash */
  175.                 *dst++ = c;
  176.                 continue;
  177.             }
  178.         }
  179. #ifndef CRUNCH
  180. # if OSK
  181.         else if (c == '\l')
  182. # else
  183.         else if (c == '\r')
  184. # endif
  185.         {
  186.             /* transliterate ^M into newline */
  187.             *dst++ = '\n';
  188.             continue;
  189.         }
  190. #endif /* !CRUNCH */
  191.         else
  192.         {
  193.             /* ordinary character, so just copy it */
  194.             *dst++ = c;
  195.             continue;
  196.         }
  197.  
  198.         /* Note: to reach this point in the code, we must have evaded
  199.          * all "continue" statements.  To do that, we must have hit
  200.          * a metacharacter that involves copying.
  201.          */
  202.  
  203.         /* if there is nothing to copy, loop */
  204.         if (!cpy)
  205.             continue;
  206.  
  207.         /* copy over a portion of the original */
  208.         while (cpy < end)
  209.         {
  210. #ifndef NO_MAGIC
  211. # ifndef CRUNCH
  212.             switch (mod)
  213.             {
  214.               case 'U':
  215.               case 'u':
  216.                 /* convert to uppercase */
  217.                 *dst++ = toupper(*cpy++);
  218.                 break;
  219.  
  220.               case 'L':
  221.               case 'l':
  222.                 /* convert to lowercase */
  223.                 *dst++ = tolower(*cpy++);
  224.                 break;
  225.  
  226.               default:
  227.                 /* copy without any conversion */
  228.                 *dst++ = *cpy++;
  229.             }
  230.  
  231.             /* \u and \l end automatically after the first char */
  232.             if (mod && (mod == 'u' || mod == 'l'))
  233.             {
  234.                 mod = 0;
  235.             }
  236. # else /* CRUNCH */
  237.             *dst++ = *cpy++;
  238. # endif /* CRUNCH */
  239. #else /* NO_MAGIC */
  240.             *dst++ = *cpy++;
  241. #endif /* NO_MAGIC */
  242.         }
  243.     }
  244.     *dst = '\0';
  245. }
  246.